import {
    BroadcastRequest,
    BroadcastResponse,
    BroadcastResponseStatus,
    BroadcastType,
    Controller,
    ControllerNo,
    GuiId,
    SpecialStoreKey,
    TimeControllerOpt
} from "./model/ControllerOpt";
import {Util} from "../utils/Util";
import {
    AllUnitAttrs,
    CaluType,
    ChangeUnitType,
    ConditionCallBack,
    MaterialInfo,
    MixRet,
    RewardType,
    SpecialEffectType,
    SpecielReward,
    TaskApplyData,
    TaskApplyType,
    TaskDoneType,
    TypeTaskRet
} from "../type/Type";
import {DataRouter} from "../frame/dataSource/DataRouter";
import {GlobalEnv} from "../utils/GlobalEnv";
import {ControllerBroadcast} from "./ControllerBroadcast";
import {SerializeBody, SerializeLoadType, TaskSerializeBody} from "./model/SerializeBody";
import {
    AttributeEnum,
    ConditionType,
    EqualType,
    MixData,
    PlayerAttribute,
    RewardItemData,
    RewardItemType,
    SaveType,
    TaskType,
    UnitType
} from "../frame/dataSource/DataModel";
import {ConfigKey, QualitySetting} from "../constant/ConfigConstant";
import {TimeController} from "./TimeController";
import Configer from "../frame/apiModel/config/Configer";
import MathUtil from "../frame/codeAdapter/MathUtil";
import {DataRouterUtil} from "../utils/router/DataRouterUtil";
import {Logger} from "../frame/apiModel/config/Logger";
import {UnitModel} from "../frame/apiModel/adapterModel/model3/UnitModel";
import {PlayerModel} from "../frame/apiModel/adapterModel/model4/PlayerModel";
import {CodeUtil} from "../frame/codeAdapter/CodeUtil";
import {ItemDataKey, PlayerDataKey} from "../frame/dataSource/DataSource";
import {ModelFactory} from "../frame/apiModel/adapterModel/model5/ModelFactory";
import {PlayerFactory} from "../frame/PlayerFactory";
import {LocModel} from "../frame/apiModel/base/LocModel";
import {ItemJson} from "../frame/apiModel/model/StoreJson";
import {ItemModel} from "../frame/apiModel/adapterModel/model3/ItemModel";
import {FinalKey} from "../constant/FinalConstant";
import {GlobalModel} from "../frame/apiModel/adapterModel/model1/GlobalModel";
import {TaskUtil} from "./util/TaskUtil";
import {ResourceKey} from "../constant/ResourceConstant";

// import {GuiController, OptType} from "./GuiController";

export class TaskController implements Controller {

    getControllerNo(): number {
        return ControllerNo.TaskController;
    }
    private static taskController: TaskController = new TaskController();

    static getInstance() {
        return TaskController.taskController;
    }
    loadByJson(json: TaskSerializeBody, player: PlayerModel) {
        const unitApplyTaskMap = player.data[PlayerDataKey.unitApplyTask];
        const archiveIndex = player.data[PlayerDataKey.archiveIndex];
        this.mapTaskSerialize(archiveIndex,  SerializeLoadType.current_global, (key, index, taskId: string) => {
            const value = json[key];
            if (!CodeUtil.isNullOrZero(value)) {
                unitApplyTaskMap[taskId] = value;
            }
        })

        const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player: player, data: {} } }
        ControllerBroadcast.getInstance().broadcast(request);
    }
    init() {
        ControllerBroadcast.getInstance().startListen(TaskController.getInstance());
    }
    private checkCondition = (activeUnit: UnitModel, conditionId: string, taskId: string, player: PlayerModel): ConditionCallBack => {
        const ret: ConditionCallBack = { success: false, successFuns: [] };
        const conditionDatas = DataRouter.getConditionDataByConditionId(conditionId);
        const setSuccessTurefun = (success: boolean) => {
            if (ret.success) {
            } else {
                if (success) {
                    ret.success = true;
                }
            }
        }
        if (conditionDatas) {
            for (let i = 0; i < conditionDatas.length; i++) {
                const conditionData = conditionDatas[i];
                const conditionType =  conditionData.type;
                const conditionValue = conditionData.value;
                const conditionNum = conditionData.num;
                const conditionEqualType = conditionData.equalType;

                let currentNum = 0;
                if (conditionValue || conditionNum) {
                    let bCheck = false;
                    switch (conditionType) {
                        case ConditionType.talk: {
                            const loc = activeUnit.loc;
                            const radius = Configer.getConfig(ConfigKey.talkTaskRange);
                            let success = false;
                            ModelFactory.getInstance().mapUnitInRange(loc, radius, (unit) => {
                                const strId = DataRouterUtil.getUnitStr(unit)
                                if (strId === conditionValue) {
                                    success = true;
                                }
                            });
                            setSuccessTurefun(success);
                            bCheck = true;
                            break;
                        }
                        case ConditionType.gather:
                        case ConditionType.kill: {
                            // 只有击杀任务统计需要taskId
                            if (taskId) {
                                // const unitData = DataRouter.getUnitDataByUnitId(conditionValue);
                                // const name = unitData.Name;
                                const unitApplyTasks = player.data[PlayerDataKey.unitApplyTask];
                                currentNum = TaskUtil.getRecordNum(unitApplyTasks, taskId, conditionValue);
                                // const fun = () => {
                                //     Util.loggerInDev(`${name}: ${currentNum}/${conditionNum}`, LogType.product, ToastType.text, player)
                                // }
                                // ret.tipFuns = fun;
                            }
                            break;
                        }
                        case ConditionType.difficult: {
                            currentNum = GlobalEnv.difficult;
                            break;
                        }
                        // ***
                        case ConditionType.skillFamily: {
                            const familyId = conditionValue;
                            const abilityRequest: BroadcastRequest = { broadcastType: BroadcastType.getAbilityBiggestFamilyLevel, controllerNo: ControllerNo.AbilityController, data: { unit: activeUnit, familyId } }
                            const response = ControllerBroadcast.getInstance().broadcast(abilityRequest);
                            if (response.status === BroadcastResponseStatus.success) {
                                currentNum = response.data.familyLevel;
                            }
                            break;
                        }
                        // ***
                        case ConditionType.heroLevel: {
                            currentNum = activeUnit.level;
                            break;
                        }
                        case ConditionType.mallUse: {
                            currentNum = player.getMallItemCount(conditionValue);
                            const fun = () => {
                                player.consumMallItemCount(conditionValue, conditionNum);
                            }
                            ret.successFuns.push(fun);
                            break;
                        }
                        case ConditionType.mallBuy: {
                            const bHave = player.getHasMallItem(conditionValue);
                            if (bHave) {
                                currentNum = 1;
                            }
                            break;
                        }
                        case ConditionType.mapLevel: {
                            currentNum = player.getMapLevel();
                            break;
                        }
                        case ConditionType.paseDifficult: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.getMaxDifficult, controllerNo: ControllerNo.StoreController, data: { player } }
                            const response = ControllerBroadcast.getInstance().broadcast(request);
                            currentNum = response.data.difficult;
                            break;
                        }
                        case ConditionType.selfUnitType: {
                            const unitId = DataRouterUtil.getUnitStr(activeUnit);
                            if (unitId === conditionValue) {
                                setSuccessTurefun(true);
                            }
                            bCheck = true;
                            break;
                        }
                        case ConditionType.onlyOneSave: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.getLastTime, controllerNo: ControllerNo.StoreController, data: { player } }
                            const response = ControllerBroadcast.getInstance().broadcast(request);
                            const time = response.data.time;
                            if (!CodeUtil.isNullOrZero(time)) {
                            } else {
                                setSuccessTurefun(true);
                            }
                            bCheck = true;
                            break;
                        }
                        case ConditionType.onlyDayOne: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.getOneDayCheck, controllerNo: ControllerNo.StoreController, data: { player } }
                            const response = ControllerBroadcast.getInstance().broadcast(request);
                            currentNum = response.data.bOneDay;
                            break;
                        }
                        case ConditionType.hasItem: {
                            currentNum = this.checkHasItemNum(player, conditionValue);
                            break;
                        }
                        case ConditionType.checkHasPet: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.checkHasPet, controllerNo: ControllerNo.UnitController, data: { player, unitId: conditionValue } }
                            const response = ControllerBroadcast.getInstance().broadcast(request);
                            const bHas = response.data.bHas;
                            if (bHas) {
                                setSuccessTurefun(true);
                            }
                            bCheck = true;
                            break;
                        }
                        case ConditionType.checkHasAch: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.getAchNum, controllerNo: ControllerNo.AchievementController, data: { player, achId: conditionValue, level: conditionNum } }
                            const response = ControllerBroadcast.getInstance().broadcast(request);
                            currentNum = response.data.achNum;
                            break;
                        }
                        case ConditionType.mallNum: {
                            currentNum = player.getMallItemCount(conditionValue);
                            break;
                        }
                        case ConditionType.wave: {
                            currentNum = GlobalEnv.wave;
                            break;
                        }
                        case ConditionType.itemNumUse: {
                            const useFamily = Configer.getConfig(ConfigKey.itemUseFamily);
                            const tempSuccess = ModelFactory.getInstance().consumItemOnUnit(activeUnit, conditionValue, useFamily, conditionNum);
                            if (tempSuccess) {
                                setSuccessTurefun(true);
                                const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.goodsBar, player: player } }
                                ControllerBroadcast.getInstance().broadcast(request);
                            }
                            bCheck = true;
                            break;
                        }
                        case ConditionType.rect: {
                            const rect = ModelFactory.getInstance().getRectModel(conditionValue)
                            const success = ModelFactory.getInstance().rectContainsUnit(rect, activeUnit)
                            setSuccessTurefun(success);
                            bCheck = true;
                            break;
                        }
                        case ConditionType.mode: {
                            if (conditionNum && conditionNum >= 0) {
                                const difficult = GlobalEnv.difficult;
                                const difficultData = DataRouterUtil.getDifficultData(difficult);
                                currentNum = difficultData.mode
                            }
                            break;
                        }
                        default: {
                            Logger.toastError(`没有命中条件类型，请验证${conditionId}的类型是否正确`, player)
                        }
                    }
                    if (bCheck) {
                        continue;
                    }
                    if (this.equalFun(currentNum, conditionNum, conditionEqualType)) {
                        setSuccessTurefun(true);
                        continue;
                    }
                }
                // ret.success = true;
                // return ret;
            }
            return ret;
        } else {
            Logger.toastError(`条件Id:${conditionId}所对应条件数据为空`)
            ret.success = true;
            return ret;
        }
    }

    equalFun = (num1: number, num2: number, equalType: EqualType) => {
        switch (equalType) {
            case EqualType.equal:{
                return num1 === num2;
            }
            case EqualType.greaterThan:{
                return num1 > num2;
            }
            case EqualType.lessThan:{
                return num1 < num2;
            }
            default: {
                return num1 === num2;
            }
        }
    }

    checkHasItemNum = (player: PlayerModel, targetItemId: string) => {
        let currentNum = 0;
        if (player?.isValid()) {
        } else {
            return currentNum;
        }
        const hero = GlobalEnv.getHero(player);
        const box = player.data[PlayerDataKey.box];
        const fun = function (this: void, item: ItemModel) {
            const tempId = DataRouterUtil.getItemStr(item.strId)
            const num = item.charges;
            if (tempId === targetItemId) {
                currentNum = currentNum + num;
            }
            return false;
        }
        hero.mapItems(fun)
        box.mapItems(fun)
        return currentNum;
    }
    clearTaskByPlayer = (player: PlayerModel) => {
        if (player?.isValid()) {
        } else {
            return false;
        }
        player.data[PlayerDataKey.unitApplyTask] = undefined;
    }
    checkConditions = (unit: UnitModel, conditionIdArr: string[], taskId: string, player: PlayerModel): { success: boolean, successFuns: (() => void)[] } => {
        const ret: { success: boolean, successFuns: (() => void)[] } = { success: true, successFuns: [] }
        for (let i = 0; i < conditionIdArr.length; i++) {
            const conditionId = conditionIdArr[i];
            const tempCheckRet = this.checkCondition(unit, conditionId, taskId, player);
            const success = tempCheckRet.success;
            ret.successFuns.push(...tempCheckRet.successFuns);
            if (success) {
            } else {
                ret.success = false;
                break;
            }
        }
        if (ret.success) {
            const funs = ret.successFuns;
            Util.doAllFuns(funs);
        }
        return ret;
    }

    loseTask = (activePlayer: PlayerModel, taskId: string) => {
        if (taskId) {
            const taskData = DataRouter.getTaskDataByTaskId(taskId);
            if (taskData) {
            } else {
                Logger.toastError(`没有对应的任务信息 ${taskId}`);
                return false;
            }
            const type = taskData.type;

            let playerArr: PlayerModel[] = [];
            if (type === TaskType.team) {
                PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                    (tempPlayer) => {
                        playerArr.push(tempPlayer);
                    }
                )
            } else {
                playerArr.push(activePlayer);
            }

            for (let i = 0; i < playerArr.length; i ++) {
                const tempPlayer = playerArr[i];
                if (tempPlayer?.isValid()) {
                } else {
                    continue;
                }
                const unitApplyTasks = tempPlayer.data[PlayerDataKey.unitApplyTask];
                const taskApplyData = unitApplyTasks[taskId];
                if (taskApplyData) {
                    const num = taskApplyData.n;
                    if (num > 0) {
                        taskApplyData.kMap = {};
                        taskApplyData.t = TaskDoneType.done;
                    } else {
                        unitApplyTasks[taskId] = undefined;
                    }
                    const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player: tempPlayer, data: {} } }
                    ControllerBroadcast.getInstance().broadcast(request);
                }
            }
        }
    }

    reflushTaskTime = (player: PlayerModel, subNum: number) => {
        const unitApplyTasks = player.data[PlayerDataKey.unitApplyTask];
        CodeUtil.mapObj(unitApplyTasks, (taskId: string, taskApplyData: TaskApplyData) => {
            const t = taskApplyData.t;
            if (t === TaskDoneType.doing) {
                const l = taskApplyData.l;
                if (l && l > 0) {
                    if (l && l > subNum) {
                        taskApplyData.l = MathUtil.toFixed(l - subNum, 2);
                    } else if (l === subNum) {
                        taskApplyData.l = 0;
                        this.loseTask(player, taskId);
                    }
                    const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player: player, data: {} } }
                    ControllerBroadcast.getInstance().broadcast(request);
                }
            }
        })
    }

    // 循环任务可以多次接受，其他任务只可以接受一次, 任务击杀数在接受时重置
    // 自动接受的任务不提示
    applyTask = (activePlayer: PlayerModel, taskId: string, applyType: TaskApplyType = TaskApplyType.normal): boolean => {
        if (taskId) {
            const taskData = DataRouter.getTaskDataByTaskId(taskId);
            if (taskData) {
            } else {
                Logger.toastError(`没有对应的任务信息 ${taskId}`);
                return false;
            }
            const currentDifficult = GlobalEnv.difficult;
            if (taskData.difficult) {
                if (taskData.difficult === currentDifficult) {
                } else {
                    return false;
                }
            }
            Logger.toastTask(`任务Id:${taskId}`, activePlayer)
            const type = taskData.type;
            let newDoneNum = 0;
            const showTaskToastFun = (str: string, bTip: boolean = false, player: PlayerModel) => {
                const tip_condition = taskData.tip_condition;
                if (!CodeUtil.isNullOrZero(tip_condition)) {
                    Logger.toastProduct(str, player)
                    // 播放标记
                    const tip_area = taskData.tip_area;

                    if (tip_area && bTip) {
                        const rect = ModelFactory.getInstance().getRectModel(tip_area);
                        const center = rect?.getCenterLocModel();
                        player.signal(center);
                    }

                    const clickTp = taskData.clickTp;
                    if (!CodeUtil.isNullOrZero(clickTp) && bTip) {
                        const rect = ModelFactory.getInstance().getRectModel(tip_area);
                        const center = rect?.getCenterLocModel();
                        const hero = GlobalEnv.getHero(player);
                        player.moveUnit(hero, center, true);
                    }
                }
            }
            let playerArr: PlayerModel[] = [];
            if (type === TaskType.team) {
                PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                    (tempPlayer) => {
                        playerArr.push(tempPlayer);
                    }
                )
            } else {
                playerArr.push(activePlayer);
            }
            for (let i = 0; i < playerArr.length; i ++) {
                const tempPlayer = playerArr[i];
                if (tempPlayer?.isValid()) {
                } else {
                    continue;
                }
                const unitApplyTasks = tempPlayer.data[PlayerDataKey.unitApplyTask];
                const taskApplyData = unitApplyTasks[taskId];
                if (taskApplyData) {
                    const doneNum = taskApplyData.n;
                    const doneType = taskApplyData.t;
                    Logger.toastTask(`当前任务状态`, tempPlayer)
                    Logger.toastTask(`当前任务完成次数:${doneNum}`, tempPlayer)
                    Logger.toastTask(`当前任务完成状态:${doneType}`, tempPlayer)
                    if (doneType === TaskDoneType.doing) {
                        if (applyType === TaskApplyType.normal || applyType === TaskApplyType.onlyFinsh) {
                            const success = this.checkTaskFinsh(tempPlayer, taskId);
                            if (success) {
                            } else {
                                showTaskToastFun(`任务未完成`, true, tempPlayer);
                            }
                        }
                        continue;
                    } else if (doneType === TaskDoneType.done) {
                        if (!CodeUtil.isNullOrZero(doneNum)) {
                            const type = taskData.type;
                            const bRe = (type === TaskType.circulate) || (type === TaskType.team);
                            if (bRe) {
                                newDoneNum = doneNum
                            } else {
                                showTaskToastFun(`任务已完成`, false, tempPlayer);
                                continue;
                            }
                        }
                    }
                }
                if (applyType === TaskApplyType.normal || applyType === TaskApplyType.onlyApply) {
                    const typeTaskRet = this.getDoingTask(tempPlayer);
                    const checkRet = this.taskNumCheck(tempPlayer, typeTaskRet, type);
                    if (checkRet) {
                    } else {
                        continue;
                    }
                    const killDataMap = this.getKillDataMap(taskId);
                    const newTaskApplyData: TaskApplyData = { kMap: killDataMap, n: newDoneNum, t: TaskDoneType.doing };
                    const strIndex = taskId;
                    tempPlayer.data[PlayerDataKey.unitApplyTask][strIndex] = newTaskApplyData;
                    // const getText = taskData.task_content;
                    // showTaskToastFun(getText, true, tempPlayer);

                    const applyRewardItem = taskData.apply_reward_item;
                    if (applyRewardItem) {
                        const hero = GlobalEnv.getHero(tempPlayer);
                        this.reward(hero, hero, RewardType.bag, applyRewardItem)
                    }

                    let timeLimit = taskData.time_limit;
                    if (!CodeUtil.isNullOrZero(timeLimit)) {
                        newTaskApplyData.l = timeLimit;
                        // const failCallBack = () => {
                        //     timeLimit = timeLimit - 1;
                        //     newTaskApplyData.l = timeLimit;
                        //     if (timeLimit <= 0) {
                        //         Logger.toastTask(`任务: ${taskData.task_name} 失败`, tempPlayer)
                        //         const rewardId = taskData.fail_reward_item;
                        //         if (rewardId) {
                        //             const hero = GlobalEnv.getHero(tempPlayer);
                        //             this.reward(hero, hero, RewardType.bag, rewardId)
                        //         }
                        //     }
                        //     const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player: tempPlayer, data: {} } }
                        //     ControllerBroadcast.getInstance().broadcast(request);
                        // }
                        // const opt = new TimeControllerOpt(undefined, failCallBack, timeLimit);
                        // TimeController.getInstance().startTimer({time: 1, opt});
                    }
                }
                const typeTaskRet = this.getDoingTask(tempPlayer);
                const data = { typeTaskRet: typeTaskRet };
                const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player: tempPlayer, data: data } }
                ControllerBroadcast.getInstance().broadcast(request);
                const req: BroadcastRequest = { controllerNo: ControllerNo.StoreController, broadcastType: BroadcastType.addStoreTask, data: { player: tempPlayer, no: ControllerNo.TaskController } }
                ControllerBroadcast.getInstance().broadcast(req);
            }
            return true
        } else {
            Logger.toastError(`taskId为空`)
            return false;
        }
    }
    getDoingTask(player: PlayerModel): TypeTaskRet {
        const typeTaskRet: TypeTaskRet = { mainTask: [], deputyTask: [], circulateTask: [], foreverTask: [], teamTask: [] };
        if (player?.isValid()) {
        } else {
            return typeTaskRet;
        }
        const unitApplyTaskMap = player.data[PlayerDataKey.unitApplyTask];
        CodeUtil.mapObj(unitApplyTaskMap, (taskId, taskApplyData) => {
            const taskData = DataRouter.getTaskDataByTaskId(taskId);
            const doneType = taskApplyData.t
            if (doneType === TaskDoneType.doing) {
            } else {
                return false;
            }
            switch (taskData?.type) {
                case TaskType.main: {
                    typeTaskRet.mainTask.push(taskData);
                    break;
                }
                case TaskType.deputy: {
                    typeTaskRet.deputyTask.push(taskData);
                    break;
                }
                case TaskType.circulate: {
                    typeTaskRet.circulateTask.push(taskData);
                    break;
                }
                case TaskType.forever: {
                    typeTaskRet.foreverTask.push(taskData);
                    break;
                }
                case TaskType.team: {
                    typeTaskRet.teamTask.push(taskData);
                    break;
                }
            }
            return false;
        })
        return typeTaskRet;
    }
    taskNumCheck(player: PlayerModel, typeTaskRet: TypeTaskRet, type: TaskType) {
        switch (type) {
            case TaskType.main:{
                const maxMainTask = Configer.getConfig(ConfigKey.maxMainTask);
                if (typeTaskRet.mainTask.length >= maxMainTask) {
                    Logger.toastError(`主线任务最多同时接受${maxMainTask}个`, player);
                    return false;
                }
                break;
            }
            case TaskType.team:{
                const maxTeamTask = Configer.getConfig(ConfigKey.maxTeamTask);
                if (typeTaskRet.teamTask.length >= maxTeamTask) {
                    Logger.toastError(`团队任务最多同时接受${maxTeamTask}个`, player);
                    return false;
                }
                break;
            }
            case TaskType.circulate:
            case TaskType.deputy:{
                const maxDeputyTask = Configer.getConfig(ConfigKey.maxDeputyTask);
                const maxCirculateTask = Configer.getConfig(ConfigKey.maxCirculateTask);
                const len = typeTaskRet.deputyTask.length + typeTaskRet.circulateTask.length;
                const max = maxDeputyTask + maxCirculateTask;
                if (len >= max) {
                    Logger.toastError(`支线任务和循环任务最多同时接受${max}个`, player);
                    return false;
                }
                break;
            }
            case TaskType.forever:{
                const maxForeverTask = Configer.getConfig(ConfigKey.maxForeverTask);
                if (typeTaskRet.foreverTask.length >= maxForeverTask) {
                    Logger.toastError(`成就任务最多同时接受${maxForeverTask}个`, player);
                    return false;
                }
                break;
            }
        }
        return true;
    }
    getKillDataMap = (taskId: string) => {
        const killDataMap: { [key: string]: number } = {};
        const taskData = DataRouter.getTaskDataByTaskId(taskId);
        if (taskData) {
        } else {
            Logger.toastError(`取击杀记录时 没有对应的任务信息 ${taskId}`)
            return killDataMap;
        }
        const conditionIds = taskData.condition;
        const conditionArr = CodeUtil.getArrBySplit(conditionIds);
        for (let i = 0; i < conditionArr.length; i ++) {
            const conditionId = conditionArr[i];
            const conditionDatas = DataRouter.getConditionDataByConditionId(conditionId);
            if (conditionDatas) {
                for (let j = 0; j < conditionDatas.length; j++) {
                    const conditionData = conditionDatas[j]
                    const conditionType = conditionData?.type;
                    if (conditionType && conditionType === ConditionType.kill || conditionType === ConditionType.gather) {
                        const value = conditionData.value;
                        if (value) {
                            killDataMap[value] = 0;
                        }
                    }
                }
            }
        }
        return killDataMap;
    }

    recordNum = (player: PlayerModel, recordId: string) => {
        const taskIds = this.isRecordId(player, recordId);
        let bChange = false;
        for (let taskIndex = 0; taskIndex < taskIds.length; taskIndex++) {
            const taskId = taskIds[taskIndex];
            const taskData = DataRouter.getTaskDataByTaskId(taskId);
            if (taskData) {
            } else {
                Logger.toastError(`记录击杀数时 没有对应的任务信息 ${taskId}`)
                return;
            }
            const type = taskData.type;
            const players: PlayerModel[] = [];
            if (type === TaskType.team) {
                PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                    (player) => {
                        players.push(player);
                    }
                )
            } else {
                players.push(player);
            }
            for (let playerIndex = 0; playerIndex < players.length; playerIndex ++) {
                const tempPlayer = players[playerIndex];
                if (tempPlayer?.isValid()) {
                } else {
                    continue
                }
                const unitApplyTasks = tempPlayer.data[PlayerDataKey.unitApplyTask];
                if (bChange) {
                } else {
                    bChange = true;
                }
                let newKillUnitNum = 1;
                const killUnitNum = TaskUtil.getRecordNum(unitApplyTasks, taskId, recordId);
                if (killUnitNum) {
                    newKillUnitNum = killUnitNum + 1;
                }
                const taskApplyData = unitApplyTasks[taskId];
                const killDataMap = taskApplyData.kMap;
                killDataMap[recordId] = newKillUnitNum;
                if (bChange) {
                    const typeTaskRet = this.getDoingTask(tempPlayer);
                    const data = { typeTaskRet: typeTaskRet };
                    const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player: tempPlayer, data: data } }
                    ControllerBroadcast.getInstance().broadcast(request);
                    const req: BroadcastRequest = { controllerNo: ControllerNo.StoreController, broadcastType: BroadcastType.addStoreTask, data: { player: tempPlayer, no: ControllerNo.TaskController } }
                    ControllerBroadcast.getInstance().broadcast(req);
                }
            }
        }
    }
    // 返回击中的任务Id
    isRecordId = (player: PlayerModel, typeId: string): string[] => {
        const taskIds = [];
        if (player?.isValid()) {
        } else {
            return taskIds;
        }
        if (typeId) {
        } else {
            return taskIds;
        }
        const unitApplyTasks = player.data[PlayerDataKey.unitApplyTask];
        if (unitApplyTasks) {
        } else {
            return taskIds;
        }
        CodeUtil.mapObj(unitApplyTasks, (key, value) => {
            const doneType = value.t;
            if (doneType === TaskDoneType.doing) {
                const killDataMap = value.kMap;
                const taskId = key;
                if (killDataMap) {
                    CodeUtil.mapObj(killDataMap,
                        (key, value) => {
                            const unitId = key;
                            if (unitId === typeId) {
                                taskIds.push(taskId);
                                return true
                            }
                        }
                    )
                }
            }
            return false
        })
        return taskIds;
    }
    clearRecordKill = (player: PlayerModel, taskId: string) => {
        if (player?.isValid()) {
        } else {
            return;
        }
        const unitApplyTasks = player.data[PlayerDataKey.unitApplyTask];
        if (unitApplyTasks) {
        } else {
            return;
        }
        const taskApplyData = unitApplyTasks[taskId];
        taskApplyData.n = taskApplyData.n + 1;
        taskApplyData.t = TaskDoneType.done;
        const killDataMap = taskApplyData.kMap;
        CodeUtil.mapObj(killDataMap,
            (key, value) => {
                killDataMap[key] = 0;
                return false
            }
        )
    }
    checkTasksFinsh = (player: PlayerModel) => {
        let success = false;
        if (player?.isValid()) {
        } else {
            return success;
        }
        const unitApplyTasks = player.data[PlayerDataKey.unitApplyTask];

        if (unitApplyTasks) {
        } else {
            return success;
        }
        if (unitApplyTasks) {
            CodeUtil.mapObj(unitApplyTasks, (key, value) => {
                const taskData = DataRouter.getTaskDataByTaskId(key);
                if (taskData) {
                } else {
                    Logger.toastError(`检查任务s是否完成时 没有目标任务信息 ${key}`)
                    return false;
                }
                const taskAuto = taskData.task_auto;
                if (!CodeUtil.isNullOrZero(taskAuto)) {
                    const taskApplyData = this.getTaskApplyData(player, key);
                    if (taskApplyData) {
                        const doneType = taskApplyData.t;
                        if (doneType === TaskDoneType.doing) {
                            success = this.checkTaskFinsh(player, key)
                        }
                    }
                }
                return false;
            })
        }
        return success;
    }
    getTaskApplyData = (player:PlayerModel, taskId: string) => {
        const unitApplyTasks = player.data[PlayerDataKey.unitApplyTask];
        const taskApplyData = unitApplyTasks[taskId];
        return taskApplyData;
    }
    checkTaskFinsh = (player: PlayerModel, taskId: string) => {
        const taskData = DataRouter.getTaskDataByTaskId(taskId);
        if (taskData) {
        } else {
            Logger.toastError(`检查任务是否完成时 没有目标任务信息 ${taskId}`)
            return false;
        }
        const conditionIds = taskData.condition;
        const conditionArr = CodeUtil.getArrBySplit(conditionIds);
        const hero = GlobalEnv.getHero(player);
        const ret = this.checkConditions(hero, conditionArr, taskId, player);
        const success = ret.success;
        if (success) {
            const type = taskData.type;
            switch (type) {
                default:
                    const finshText = taskData.task_get_content;
                    // 播放任务完成的文字提示
                    Logger.toastProduct(finshText, player)
                    const soundName = taskData.pay_speech;
                    if (soundName) {
                        // todo 播放声音
                        // StartSoundForPlayerBJ(player, soundName);
                    }
                    const rewardId = taskData.task_reward_item;
                    const unit = GlobalEnv.getHero(player);
                    this.clearRecordKill(player, taskId);
                    this.reward(unit, unit, RewardType.bag, rewardId);
                    break;
            }
            const req: BroadcastRequest = { controllerNo: ControllerNo.StoreController, broadcastType: BroadcastType.addStoreTask, data: { player, no: ControllerNo.TaskController } }
            ControllerBroadcast.getInstance().broadcast(req);
            const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.taskButton, player, data: {} } }
            ControllerBroadcast.getInstance().broadcast(request);
        }
        return success;
    }
    clearStoreKey(player: PlayerModel, key: string) {
        player.setStoredString(Util.getStoreKey('', key), '0', false);
    }
    clearLockKey (player: PlayerModel) {
        this.clearStoreKey(player, SpecialStoreKey.lockKey)
        Logger.toastProduct('解除作弊锁!', player)
    }
    specielReward = (activeUnit: UnitModel, rewardId: string) => {
        switch (rewardId) {
            case SpecielReward.clearLock: {
                const player = PlayerFactory.getInstance().getUnitOwner(activeUnit);
                this.clearLockKey(player)
                return true;
            }
            case SpecielReward.integralCompensate: {
                const maxIntegral = Configer.getConfig(ConfigKey.maxIntegral);
                const player = PlayerFactory.getInstance().getUnitOwner(activeUnit);
                const request: BroadcastRequest = { broadcastType: BroadcastType.rewardIntegral, controllerNo: ControllerNo.AchievementController, data: { player: player, num: maxIntegral - 1 } }
                ControllerBroadcast.getInstance().broadcast(request);
                return true;
            }
            case SpecielReward.freeExpCompensate: {
                const player = PlayerFactory.getInstance().getUnitOwner(activeUnit);
                const request: BroadcastRequest = { broadcastType: BroadcastType.rewardFreeExp, controllerNo: ControllerNo.AchievementController, data: { player: player, num: 1000000 } }
                ControllerBroadcast.getInstance().broadcast(request);
                return true;
            }
        }
        return false;
    }
    dropFunction = (killer: UnitModel, killed: UnitModel) => {
        let realKiller = killer;

        const player = GlobalEnv.getBlongPlayer(killed);
        if (player?.isValid()) {
            realKiller = GlobalEnv.getHero(player)
        }

        if (realKiller?.isValid()) {
        } else {
            Logger.toastError('掉落所有者不生效，请联系作者处理！')
            return;
        }

        const unitIdStr = killed.strId;
        const unitData = DataRouter.getUnitDataByUnitId(unitIdStr);
        const useBossRewardLoc: number = Configer.getConfig(ConfigKey.useBossRewardLoc);

        if (unitData) {
            const unitType = unitData.unit_type;
            const rewardId = unitData.reward;
            if (rewardId) {
                // Logger.toastSys(`掉落Id${rewardId}`, killerPlayer)
                switch (unitType) {
                    case UnitType.boss: {
                        if (!CodeUtil.isNullOrZero(useBossRewardLoc)) {
                            PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                                (player: PlayerModel) => {
                                    const rewardLoc = player.startLocation;
                                    TaskController.getInstance().reward(realKiller, killed, RewardType.floor, rewardId, rewardLoc);
                                }
                            )
                            break;
                        }
                    }
                    default: {
                        const rewardLoc = killed.loc;
                        TaskController.getInstance().reward(realKiller, killed, RewardType.floor, rewardId, rewardLoc);
                        break;
                    }
                }
            }
        } else {
            Logger.toastWarn(`单位${unitIdStr}不是单位表中定义的单位`);
        }
    }

    getScatteredPoint(len: number, loc: LocModel, interval: number) {
        const retArr: LocModel[] = [];
        if (loc) {
        } else {
            return retArr
        }
        const sqrt = MathUtil.sqrt(len);
        const row = MathUtil.ceil(sqrt);
        const col = MathUtil.floor(sqrt);
        const halfRow = MathUtil.floor(row / 2)
        const halfCol = MathUtil.floor(col / 2)

        const rewardX = loc.x;
        const rewardY = loc.y;

        const startX = rewardX - (halfRow * interval);
        const startY = rewardY + (halfCol * interval)

        for (let i = 0; i < len; i ++) {
            const callBack = () => {
                const rowIndex = i % row;
                const colIndex = MathUtil.floor(i / row);

                let tempLoc: LocModel;

                if (loc) {
                    const x = startX + interval * rowIndex;
                    const y = startY - interval * colIndex;

                    tempLoc = new LocModel(x, y);
                }
                if (tempLoc) {
                    retArr.push(tempLoc);
                }
            }
            callBack();
        }
        return retArr;
    }
    // 传入rewardLoc时奖励物品类型为在地上时创建在获得奖励的人脚下  只要有一个人奖励成功就返回ture
    reward = (activeUnit: UnitModel, targetUnit: UnitModel | void, rewardType: RewardType, rewardId: string, rewardLoc?: LocModel) => {
        let newUnit = activeUnit;

        let success = false;

        const player = PlayerFactory.getInstance().getUnitOwner(newUnit);

        const specielRewardRet = this.specielReward(activeUnit, rewardId);
        if (specielRewardRet) {
            return true;
        }

        const groups = this.getRewardGroupByRewardId(newUnit, rewardId);

        if (groups) {
        } else {
            Logger.toastError(`奖励Id${rewardId}没有对应奖励组，很可能是无意义的Id，可以考虑删除`);
            return false;
        }


        const itemGroups: RewardItemData[] = [];

        const showEffect = (rewardItemData: RewardItemData, rewardUnit: UnitModel, effectLoc: LocModel) => {
            let tempLoc: LocModel = effectLoc;
            if (tempLoc) {
            } else {
                tempLoc = rewardUnit.loc;
            }
            const self_effects = rewardItemData.self_effects;
            const self_effects_time = rewardItemData.self_effects_time;
            const self_effects_point = rewardItemData.self_effects_point;
            const self_effects_scale = rewardItemData.self_effects_scale;
            if (self_effects) {
                TimeController.addSpecialEffectByResourceIdFun(rewardUnit, self_effects, self_effects_time, tempLoc, self_effects_point, SpecialEffectType.unit, self_effects_scale);
            }

            // 目标点特效
            const point_effects = rewardItemData.point_effects;
            const point_effects_time = rewardItemData.point_effects_time;
            const point_effects_scale = rewardItemData.point_effects_scale;
            if (point_effects) {
                TimeController.addSpecialEffectByResourceIdFun(rewardUnit, point_effects, point_effects_time, tempLoc, undefined, SpecialEffectType.point, point_effects_scale);
            }
        }
        for (let i = 0; i < groups.length; i ++) {
            const group = groups[i];
            const type = group.type;
            let num = group.number;
            if (num) {
            } else {
                num = 1
            }
            if (type === RewardItemType.item) {
                for (let numIndex = 0; numIndex < num; numIndex ++) {
                    itemGroups.push(group);
                }
            }
        }
        const dropSpace: number = Configer.getConfig(ConfigKey.dropSpace);
        const scatterPoints = this.getScatteredPoint(itemGroups.length, rewardLoc, dropSpace);
        for (let i = 0; i < itemGroups.length; i ++) {
            const group = itemGroups[i];
            const callBack = () => {
                const tempLoc = scatterPoints[i];
                const itemId = group.itemId;
                const protectTime = group.guard_time;
                showEffect(group, activeUnit, tempLoc);
                this.rewardItem(activeUnit, rewardType, itemId, protectTime, tempLoc);
            }
            const intervalTime = group.interval_time;
            if (!CodeUtil.isNullOrZero(intervalTime)) {
                const timerOpt = new TimeControllerOpt(undefined, callBack, 1);
                TimeController.getInstance().startTimer({time: intervalTime * i, opt: timerOpt});
            } else {
                callBack();
            }
        }

        if (groups) {
            Logger.toastTask(`最终掉落数目: ${groups.length}`, player);
            for (let i = 0; i < groups.length; i ++) {
                let tempSuccess = true;
                const group = groups[i];
                const itemId = group.itemId;
                let strNum = 1;
                if (group.number) {
                    strNum = group.number;
                }
                const num = MathUtil.toNumber(strNum);
                const type = group.type;
                const bAll = group.bAll;
                Logger.toastTask(`掉落类型: ${group.type}`, player);

                const players: PlayerModel[] = [];

                if (!CodeUtil.isNullOrZero(bAll)) {
                    PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                        (tempPlayer) => {
                            players.push(tempPlayer)
                        }
                    )
                } else {
                    players.push(player)
                }

                for (let playerIndex = 0; playerIndex < players.length; playerIndex++) {
                    const tempPlayer = players[playerIndex];
                    // 除了全体失败 全体胜利是被动奖励外，其他都是主动奖励, 被动奖励不判断玩家是否在线
                    switch (type) {
                        case RewardItemType.toLose:
                        case RewardItemType.invulnerable:
                        case RewardItemType.whiteAttr: {
                            break;
                        }
                        default: {
                            // 调用奖励接口时有可能 玩家已经退出游戏或游戏失败
                            if (tempPlayer?.isNotEndPlaying()) {
                            } else {
                                continue;
                            }
                        }
                    }

                    switch (type) {
                        case RewardItemType.item: {
                            break;
                        }
                        case RewardItemType.transAll:
                        case RewardItemType.trans: {
                            const transUnits: UnitModel[] = [];
                            if (type === RewardItemType.transAll) {
                                const pets = Util.getAllBattlePetAndSummoned(tempPlayer);
                                transUnits.push(...pets)
                                const hero = GlobalEnv.getHero(tempPlayer);
                                transUnits.push(hero)
                            } else {
                                transUnits.push(newUnit)
                            }
                            const transData = DataRouter.getTransDataByTransId(group.itemId);
                            if (transData) {
                                const request: BroadcastRequest = { broadcastType: BroadcastType.useTransData, controllerNo: ControllerNo.UnitController, data: { units: transUnits, transData: transData, bRandom: true } }
                                ControllerBroadcast.getInstance().broadcast(request);
                            } else {
                                Logger.toastError(`没有对应的传送消息 ${group.itemId}`);
                            }
                            break;
                        }
                        case RewardItemType.exp: {
                            const isOnly = DataRouterUtil.checkUnitUseAttr(newUnit);
                            if (isOnly) {
                                newUnit.setExperience(newUnit.experience + num);
                            } else {
                                const hero = GlobalEnv.getHero(tempPlayer);
                                hero.setExperience(hero.experience + num);
                            }
                            break;
                        }
                        case RewardItemType.coin: {
                            tempPlayer.gold = tempPlayer.gold + num;
                            break;
                        }
                        case RewardItemType.wood: {
                            tempPlayer.lumber = tempPlayer.lumber + num;
                            break;
                        }
                        case RewardItemType.changeHero: {
                            // 替换单位不继承属性，继承四个基础技能
                            const unitId = itemId;
                            const hero = GlobalEnv.getHero(tempPlayer);
                            const request: BroadcastRequest = { broadcastType: BroadcastType.changeUnit, controllerNo: ControllerNo.UnitController, data: { unitId, unit: hero, changeUnitType: ChangeUnitType.hero } }
                            const res = ControllerBroadcast.getInstance().broadcast(request);
                            const data = res.data;
                            newUnit = data.unit;
                            break;
                        }
                        case RewardItemType.achievement: {
                            const achievementId = itemId;
                            const achievementRequest: BroadcastRequest = { broadcastType: BroadcastType.addAchievement, controllerNo: ControllerNo.AchievementController, data: { player: tempPlayer, achievementId, num: num } }
                            const res = ControllerBroadcast.getInstance().broadcast(achievementRequest);
                            const data = res.data;
                            tempSuccess = data.success;
                            break;
                        }
                        case RewardItemType.enemy: {
                            const unitId = itemId;
                            const unitNum = num;
                            const loc = activeUnit.loc;
                            const enemyTeam = Configer.getConfig(ConfigKey.enemyTeam) as number;
                            const enemyPlayer = GlobalEnv.getTeamFreePlayer(enemyTeam)
                            const request: BroadcastRequest = { broadcastType: BroadcastType.createUnit, controllerNo: ControllerNo.UnitController, data: { player: enemyPlayer, unitId: unitId, unitNum: unitNum, loc: loc } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.wave: {
                            // 替换单位不继承属性，继承四个基础技能
                            const currentWave = GlobalEnv.wave;
                            const difficultNum = GlobalEnv.difficult;
                            const tempWave = currentWave + num;
                            const difficultDatas = DataRouter.getDifficultDatas();
                            const difficultData = difficultDatas[difficultNum];
                            const maxWave = difficultData.wave;
                            if (tempWave < 1) {
                                tempSuccess = false;
                                Logger.toastProduct(`当前关卡数不能小于1`, tempPlayer);
                            } else if (tempWave > maxWave) {
                                tempSuccess = false;
                                Logger.toastProduct(`当前关卡数不能大于${maxWave}`, tempPlayer);
                            } else {
                                GlobalEnv.wave = tempWave
                            }
                            break;
                        }
                        case RewardItemType.resetUnit: {
                            const unit = newUnit;
                            const request: BroadcastRequest = { broadcastType: BroadcastType.resetUnit, controllerNo: ControllerNo.UnitController, data: { unit } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.initMonster: {
                            const monsterData = DataRouter.getGenerateDataByGenerateId(itemId);
                            if (monsterData) {
                                const request: BroadcastRequest = { broadcastType: BroadcastType.checkToInitMonster, controllerNo: ControllerNo.UnitController, data: { monsterData } }
                                ControllerBroadcast.getInstance().broadcast(request);
                            } else {
                                tempSuccess = false;
                                Logger.toastError(`奖励生成怪物时，对应生成信息不存在 ${itemId}`);
                            }
                            break;
                        }
                        case RewardItemType.clearItem: {
                            // todo 清理装备
                            break;
                        }
                        case RewardItemType.technology: {
                            const technologyId = itemId;
                            const level = num;
                            tempPlayer.setTech(technologyId, level)
                            break;
                        }
                        case RewardItemType.populationMax: {
                            tempPlayer.allFood = tempPlayer.allFood + num;
                            break;
                        }
                        case RewardItemType.changeBox: {
                            // 替换单位不继承属性，继承四个基础技能
                            const unitId = itemId;
                            const box = GlobalEnv.getBox(tempPlayer);
                            if (box) {
                                const request: BroadcastRequest = { broadcastType: BroadcastType.changeUnit, controllerNo: ControllerNo.UnitController, data: { unitId, unit: box, changeUnitType: ChangeUnitType.box } }
                                ControllerBroadcast.getInstance().broadcast(request);
                            }
                            break;
                        }
                        case RewardItemType.changeHeroModel: {
                            // 替换单位不继承属性，继承四个基础技能
                            const model = itemId;
                            const hero = GlobalEnv.getHero(tempPlayer);
                            hero.setModelPath(model);
                            break;
                        }
                        case RewardItemType.task: {
                            // 替换单位不继承属性，继承四个基础技能
                            const taskId = itemId;
                            this.applyTask(tempPlayer, taskId);
                            break;
                        }
                        case RewardItemType.toWin: {
                            GlobalEnv.setBeWin(tempPlayer, true)
                            break;
                        }
                        case RewardItemType.toLose: {
                            if (targetUnit) {
                                const targetPlayer = PlayerFactory.getInstance().getUnitOwner(targetUnit);
                                GlobalEnv.setBeLose(targetPlayer, true)
                            }
                            break;
                        }
                        case RewardItemType.removeSkill: {
                            const abilityId = itemId;
                            const request: BroadcastRequest = { broadcastType: BroadcastType.removeSkill, controllerNo: ControllerNo.AbilityController, data: { unit: newUnit, abilityId: abilityId } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.skill: {
                            const abilityId = itemId;
                            const request: BroadcastRequest = { broadcastType: BroadcastType.learnSkill, controllerNo: ControllerNo.AbilityController, data: { unit: newUnit, abilityId: abilityId } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.learnSkillByFamilyLv: {
                            const familyId = itemId;
                            const level = num;
                            const request: BroadcastRequest = { broadcastType: BroadcastType.learnSkillByFamilyLv, controllerNo: ControllerNo.AbilityController, data: { unit: newUnit, familyId: familyId, level: level } }
                            const res = ControllerBroadcast.getInstance().broadcast(request);
                            const data = res.data;
                            tempSuccess = data.success;
                            break;
                        }
                        case RewardItemType.removeSkillByFamilyLv: {
                            const familyId = itemId;
                            const level = num;
                            const request: BroadcastRequest = { broadcastType: BroadcastType.removeSkillByFamilyLv, controllerNo: ControllerNo.AbilityController, data: { unit: newUnit, familyId: familyId, level: level } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.pet: {
                            const unitId = itemId;
                            const request: BroadcastRequest = { broadcastType: BroadcastType.addPet, controllerNo: ControllerNo.UnitController, data: { unitId: unitId, player: tempPlayer } }
                            const res = ControllerBroadcast.getInstance().broadcast(request);
                            const data = res.data;
                            tempSuccess = data.success;
                            break;
                        }
                        case RewardItemType.resumePet: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.resumePet, controllerNo: ControllerNo.UnitController, data: { player: tempPlayer } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.resumeHero: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.resumeHero, controllerNo: ControllerNo.UnitController, data: { player: tempPlayer } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.maxMonsterNum: {
                            tempPlayer.addMaxAttackMonsterNum(num)
                            break;
                        }
                        case RewardItemType.integral: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.rewardIntegral, controllerNo: ControllerNo.AchievementController, data: { player: tempPlayer, num: num } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.qualityMix: {
                            const materialInfos: MaterialInfo[] = this.getMixGoodsInfoInUnitBag(activeUnit);
                            tempSuccess = TaskController.getInstance().toMixItemByQuality(activeUnit, materialInfos)
                            break;
                        }
                        case RewardItemType.backHome: {
                            const startLoc = tempPlayer.startLocation;
                            tempPlayer.moveUnit(activeUnit, startLoc, true)
                            break;
                        }
                        case RewardItemType.music: {
                            const path = itemId;
                            TimeController.getInstance().startBackMusic(path, num);
                            break;
                        }
                        case RewardItemType.invulnerable: {
                            newUnit.invulnerable = true;
                            const canelCallBack = () => {
                                newUnit.invulnerable = false;
                            }
                            const timerOpt = new TimeControllerOpt(undefined, canelCallBack, 1);
                            TimeController.getInstance().startTimer({ time: num, opt: timerOpt });
                            break;
                        }
                        case RewardItemType.whiteAttr: {
                            const attrEnumArr = CodeUtil.getArrBySplit(itemId);
                            const attrAddArr = CodeUtil.getArrBySplit(strNum);
                            const request: BroadcastRequest = { broadcastType: BroadcastType.getAttribute, controllerNo: ControllerNo.UnitController, data: { unit: newUnit } }
                            const res = ControllerBroadcast.getInstance().broadcast(request);
                            const attr: AllUnitAttrs = res.data.attr;
                            for (let i = 0; i < attrEnumArr.length; i++) {
                                const attrEnum = DataRouterUtil.getNumByArr(attrEnumArr, i);
                                const add = DataRouterUtil.getNumByArr(attrAddArr, i);
                                Util.caluAbilityAttr(newUnit, player, undefined, attr.whiteAttr, undefined, attrEnum, attrEnum, add, 0, CaluType.add, false, true, 'reward')
                            }
                            break;
                        }
                        case RewardItemType.stopWave: {
                            const attackTimer = GlobalEnv.waveTimer;
                            if (attackTimer) {
                                Logger.toastProduct('怪物停止进攻')
                                attackTimer.pause();
                                const canelCallBack = () => {
                                    attackTimer.resume();
                                }
                                const timerOpt = new TimeControllerOpt(undefined, canelCallBack, 1);
                                TimeController.getInstance().startTimer({ time: num, opt: timerOpt });
                            } else {
                                Logger.toastProduct('请在倒计时中使用', player)
                            }
                            break;
                        }
                        case RewardItemType.removeItem: {
                            newUnit.mapItems(
                                (item, index) => {
                                    const str = item.strId;
                                    if (str === itemId) {
                                        ModelFactory.getInstance().unitRemoveItem(newUnit, item)
                                        return true;
                                    }
                                }
                            )
                            break;
                        }
                        case RewardItemType.handBookExp: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.rewardFreeExp, controllerNo: ControllerNo.AchievementController, data: { player: tempPlayer, num: num } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.startLoc: {
                            const rect = ModelFactory.getInstance().getRectModel(itemId);
                            if (rect) {
                                const loc = rect.getCenterLocModel();
                                tempPlayer.data[PlayerDataKey.startLoc] = loc;
                                // const hero = GlobalEnv.getHero(tempPlayer);
                                // tempPlayer.moveUnit(hero, loc, true);
                            }
                            break;
                        }
                        case RewardItemType.talent: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.showUi, controllerNo: ControllerNo.GuiController, data: { player: tempPlayer, guiId: GuiId.chooseAchBar } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        case RewardItemType.addSeller: {
                            GlobalModel.addItemToAllStock(itemId, num);
                            break;
                        }
                        case RewardItemType.removeSeller: {
                            GlobalModel.removeItemFromAllStock(itemId);
                            break;
                        }
                        case RewardItemType.removeAchievement: {
                            const request: BroadcastRequest = { broadcastType: BroadcastType.removeAchievement, controllerNo: ControllerNo.AchievementController, data: { player: tempPlayer, achievementId: itemId } }
                            ControllerBroadcast.getInstance().broadcast(request);
                            break;
                        }
                        default: {
                            Logger.toastError(`${rewardId} 没有对应的奖励类型`);
                            break;
                        }
                    }
                    showEffect(group, activeUnit, rewardLoc);
                    const desc = group.descript;
                    if (desc) {
                        Logger.toastProduct(desc, tempPlayer);
                    }
                    if (success) {
                    } else {
                        success = tempSuccess;
                    }
                }
            }
        }
        return success;
    }

    // winAlone = (player: PlayerModel) => {
    //     PlayerFactory.getInstance().mapAllPlayingPlayer(
    //         (tempPlayer) => {
    //             if (player === tempPlayer) {
    //                 this.toWin(tempPlayer);
    //             } else {
    //                 this.toLose(tempPlayer);
    //             }
    //         }
    //     )
    // }
    toWin = (player: PlayerModel) => {
        const beEnd = GlobalEnv.getBeEnd(player);
        if (beEnd) {
            return;
        }
        player.data[PlayerDataKey.bWined] = true;

        const request: BroadcastRequest = { broadcastType: BroadcastType.showTextUi, controllerNo: ControllerNo.GuiController, data: { uiName: ResourceKey.win, autoClose: true, player: player } }
        ControllerBroadcast.getInstance().broadcast(request);
        const storeRequest: BroadcastRequest = { broadcastType: BroadcastType.toWinStore, controllerNo: ControllerNo.StoreController, data: { player: player } }
        ControllerBroadcast.getInstance().broadcast(storeRequest);
        Logger.toastProduct(`游戏胜利!`, player);
        const winCallBack = function () {
            // player.toWin()
            TaskController.getInstance().checkAllWin();
        }
        const winDelay = Configer.getConfig(ConfigKey.winDelay)
        const time = winDelay as number;
        const opt = new TimeControllerOpt(undefined, winCallBack, 1);
        TimeController.getInstance().startTimer({time, opt});
    }
    toLose = (player: PlayerModel) => {
        const beEnd = GlobalEnv.getBeEnd(player);
        if (beEnd) {
            return;
        }
        player.data[PlayerDataKey.bLosed] = true;

        const failDelay = Configer.getConfig(ConfigKey.failDelay)
        const time = failDelay as number;
        Logger.toastProduct(`游戏失败!${time}秒后清除玩家所有单位`, player);
        const request: BroadcastRequest = { broadcastType: BroadcastType.showTextUi, controllerNo: ControllerNo.GuiController, data: { uiName: ResourceKey.lose, autoClose: true, player: player } }
        ControllerBroadcast.getInstance().broadcast(request);
        const storeRequest: BroadcastRequest = { broadcastType: BroadcastType.toFaildStore, controllerNo: ControllerNo.StoreController, data: { player: player } }
        ControllerBroadcast.getInstance().broadcast(storeRequest);
        const failCallBack = function () {
            const request: BroadcastRequest = { broadcastType: BroadcastType.clearUnitByPlayer, controllerNo: ControllerNo.UnitController, data: { player: player } }
            ControllerBroadcast.getInstance().broadcast(request);
            TaskController.getInstance().checkAllLose();
        }
        const opt = new TimeControllerOpt(undefined, failCallBack, 1);
        TimeController.getInstance().startTimer({time, opt});
    }
    checkAllWin() {
        let allWin = true;
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (tempPlayer) => {
                const tempWin = tempPlayer.data[PlayerDataKey.bWined]
                if (tempWin) {
                } else {
                    allWin = false;
                }
            }
        )
        if (allWin) {
            GlobalModel.bStop = true;
            PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                (tempPlayer) => {
                    tempPlayer.toWin();
                }
            )
        }
    }
    checkAllLose() {
        let allLose = true;
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (tempPlayer) => {
                allLose = false;
            }
        )
        if (allLose) {
            GlobalModel.bStop = true;
            PlayerFactory.getInstance().mapAllPlayer(
                (tempPlayer) => {
                    tempPlayer.toLose();
                }
            )
        }
    }
    rewardItem = (activeUnit: UnitModel, rewardType: RewardType, itemId: string, protectTime: number = 0, rewardLoc?: LocModel) => {
        if (activeUnit) {
        } else {
            Logger.toastError('无法奖励给不存在的单位');
            return;
        }
        const activeLoc = activeUnit.loc;
        const player = PlayerFactory.getInstance().getUnitOwner(activeUnit);
        const itemJson: ItemJson = { id: itemId, n: 0, af: '', cd: 0, lv: 0 }
        let item: ItemModel;
        let tempRewardLoc: LocModel;

        if (rewardLoc) {
            tempRewardLoc = rewardLoc
        } else {
            tempRewardLoc = activeLoc
        }
        item = ModelFactory.getInstance().createItemInPoint(itemJson, tempRewardLoc, true);
        if (rewardType === RewardType.bag) {
            const getFun = () => {
                ModelFactory.getInstance().unitAddItem(activeUnit, item)
            }
            const timerOpt = new TimeControllerOpt(undefined, getFun, 1);
            TimeController.getInstance().startTimer({ time: 0.01, opt: timerOpt });
        } else {
            const protection: number = protectTime;

            // 掉落物品保护期
            if (!CodeUtil.isNullOrZero(protection) && rewardLoc) {
                item.data[ItemDataKey.protectTime] = protection;
                const clearFun = () => {
                    const currentProtection = item.data[ItemDataKey.protectTime];
                    const newProtection = currentProtection - 1
                    DataRouterUtil.bindItemBlong(item, player)
                    if (newProtection >= 0) {
                        item.data[ItemDataKey.protectTime] = newProtection;
                    }
                }
                const timerOpt = new TimeControllerOpt(undefined, clearFun, protection);
                TimeController.getInstance().startTimer({ time: 1, opt: timerOpt });
            }
        }
    }
    getRewardGroupByRewardId =  (activeUnit: UnitModel, rewardId: string, num: number = 1): RewardItemData[] => {
        if (rewardId) {
        } else {
            return [];
        }
        const player = PlayerFactory.getInstance().getUnitOwner(activeUnit)
        if (player?.isValid()) {
        } else {
            return [];
        }
        Logger.toastTask(`掉落Id${rewardId}`, player);
        const dropGroups = DataRouter.getRewardGroupDataByRewardGroupId(rewardId);
        const retGroups: RewardItemData[] = [];
        const attr: PlayerAttribute = player.data[PlayerDataKey.newestAttrs];
        if (dropGroups) {
            Logger.toastTask(`根据随机数与掉落几率计算掉落组`, player);
            for (let i = 0; i < dropGroups.length; i ++) {
                const randomItem = player.getRandomInt(0, 100);
                // const randomItem = 100;
                Logger.toastTask(`是否掉落的随机数${randomItem}`, player);
                // 4
                const dropGroup = dropGroups[i];
                const type = dropGroup.type;

                const protectTime = dropGroup.guard_time;
                const num = dropGroup.num;
                const intervalTime = dropGroup.interval_time;
                Logger.toastTask(`第${i + 1}个掉落基础几率：${dropGroup.probability}`, player);

                let lucky = GlobalEnv.luckyRadix;
                if (attr) {
                    lucky = attr[AttributeEnum.luckyValue];
                }

                // 3
                Logger.toastTask(`幸运值：${lucky}`, player);
                const addRadix = dropGroup.probability * (lucky / 100);
                const newProbability = dropGroup.probability + addRadix;
                Logger.toastTask(`幸运增益后的几率：${newProbability}`, player);
                if (newProbability < randomItem) {
                    Logger.toastTask(`掉落几率小于随机数，不掉落`, player);
                    continue;
                }
                const rewardItems = DataRouter.getRewardItemsByRewardGroupId(dropGroup.dataId);
                // 根据权重计算每个掉落组最终的掉落结果
                if (rewardItems) {
                } else {
                    Logger.toastTask(`奖励组${dropGroup.dataId} 没有对应奖励！`, player);
                    continue;
                }

                const typeCheck = GlobalEnv.checkPlayerDropRecord(player, dropGroup.rewardId, type);
                if (!CodeUtil.isNullOrZero(typeCheck)) {
                } else {
                    continue;
                }


                const pool: RewardItemData[] = [];
                for (let i = rewardItems.length - 1; i >= 0 ; i --) {
                    const rewardItem = rewardItems[i];
                    const conditionIds = rewardItem.condition;
                    const conditionArr = CodeUtil.getArrBySplit(conditionIds);
                    const ret = this.checkConditions(activeUnit, conditionArr, undefined, player);
                    const bCheck = ret.success;
                    if (bCheck) {
                        pool.push(rewardItem);
                    } else {
                        Logger.toastTask(`掉落组：${rewardItem.group_Id} 因不满足掉落条件无法掉落`, player);
                    }
                }
                const rets = DataRouterUtil.getDataModelByWeight(player, pool, num);
                for (let i = 0; i < rets?.length; i ++) {
                    const ret = rets[i];
                    if (ret && ret.id) {
                        const retGroup = DataRouter.getRewardItemByRewardId(ret.id);
                        if (retGroup) {
                            const newRet: RewardItemData = JSON.parse(JSON.stringify(retGroup));
                            newRet.guard_time = protectTime;
                            newRet.interval_time = intervalTime;
                            newRet.number = newRet.number * typeCheck;

                            retGroups.push(newRet);
                        }
                    }
                }
            }
            return retGroups;
        }
    }
    applyAutoTask = (player: PlayerModel) => {
        const taskDatas = DataRouter.getTaskDatas();
        for (let i = 0; i < taskDatas.length; i++) {
            const taskData = taskDatas[i];
            const auto = taskData.start_auto;
            const taskId = taskData.id;
            if (!CodeUtil.isNullOrZero(auto)) {
                this.applyTask(player, taskId, TaskApplyType.onlyApply);
            }
        }
    }
    notify(request: BroadcastRequest): BroadcastResponse {
        const ret: BroadcastResponse = { controllerNo: this.getControllerNo(), data: {}, status: BroadcastResponseStatus.success };
        const type = request.broadcastType;
        const data = request.data;
        switch (type) {
            case BroadcastType.serialize: {
                const player: PlayerModel = data.player;
                const serializeBody: SerializeBody = this.serialize(player);
                ret.data = { serializeBody };
                break;
            }
            case BroadcastType.recordKillUnitNum: {
                const player: PlayerModel = data.player;
                const unitId: string = data.unitId;
                this.recordNum(player, unitId);
                break;
            }
            case BroadcastType.applyAutoTask: {
                const player: PlayerModel = data.player;
                this.applyAutoTask(player);
                break;
            }
            case BroadcastType.toApplyTask: {
                const player: PlayerModel = data.player;
                const taskId: string = data.taskId;
                this.applyTask(player, taskId);
                break;
            }
            case BroadcastType.dropFun: {
                const killer: UnitModel = data.killer;
                const killed: UnitModel = data.killed;
                this.dropFunction(killer, killed);
                break;
            }
            case BroadcastType.reward: {
                const activeUnit: UnitModel = data.activeUnit;
                const targetUnit: UnitModel = data.targetUnit;
                const rewardType: RewardType = data.rewardType;
                const rewardId: string = data.rewardId;
                const rewardLoc: LocModel = data.rewardLoc;
                this.reward(activeUnit, targetUnit, rewardType, rewardId, rewardLoc);
                break;
            }
            default :
                ret.status = BroadcastResponseStatus.failed;
                break;
        }
        return ret;
    }
    serialize(player: PlayerModel): TaskSerializeBody {
        const archiveIndex = player.data[PlayerDataKey.archiveIndex];
        const storeTask: TaskSerializeBody = player.data[PlayerDataKey.storeCurrent][ControllerNo.TaskController];
        const applyDatas = player.data[PlayerDataKey.unitApplyTask];
        this.mapTaskSerialize(archiveIndex,   SerializeLoadType.current_global, (key, index, taskId) => {
            const value = applyDatas[taskId];
            if (!CodeUtil.isNullOrZero(value)) {
                storeTask[key] = value;
            }
        });
        const taskSerializeBody = storeTask;
        return taskSerializeBody;
    }


    // ItemRewardUtil

    checkGet(unit: UnitModel, item: ItemModel): boolean {
        const protect = item.data[ItemDataKey.protectTime];
        const player = PlayerFactory.getInstance().getUnitOwner(unit);
        const loc = unit.loc;
        const playerId = player.playerId;
        if (!CodeUtil.isNullOrZero(protect)) {
            Logger.toastProduct(`${protect}秒后可拾取!`, player)
            unit.dropItem(item, loc)
            return false;
        }
        const ownerId = item.data[ItemDataKey.ownerId];
        if (ownerId > 0 && ownerId !== playerId) {
            Logger.toastProduct(`这件物品不属于你!`, player)
            unit.dropItem(item, loc)
            return false;
        }
        // {
        // const playerName = GetPlayerName(player);
        // Util.loggerInDev(`玩家${playerName} 疑似作弊物品，清空身上所有物品!`, LogType.error);
        // GoodController.getInstance().clearUnitGoodSlot(unit);
        // }
        return true
    }

    itemCheckConditions(unit: UnitModel, player: PlayerModel, itemId: string) {
        const itemData = DataRouter.getItemDataByItemId(itemId);
        // 只有物品需要这个判断
        if (itemData) {
            const conditionIds = itemData.condition;
            const conditionArr = CodeUtil.getArrBySplit(conditionIds);
            const ret = TaskController.getInstance().checkConditions(unit, conditionArr, undefined, player);
            const success = ret.success;
            return success;
        }
    }
    itemCheckGetConditions(unit: UnitModel, player: PlayerModel, itemId: string) {
        const itemData = DataRouter.getItemDataByItemId(itemId);
        // 只有物品需要这个判断
        if (itemData) {
            const conditionIds = itemData.getCondition;
            const conditionArr = CodeUtil.getArrBySplit(conditionIds);
            const ret = TaskController.getInstance().checkConditions(unit, conditionArr, undefined, player);
            const success = ret.success;
            return success;
        }
    }
    useRewardsItem(useUnit: UnitModel, itemId: string) {
        const itemData = DataRouter.getItemDataByItemId(itemId);
        const rewardId = itemData?.type_id;
        if (rewardId) {
            return TaskController.getInstance().reward(useUnit, useUnit, RewardType.bag, rewardId)
        } else {
            Logger.toastError(`没有找到对应的奖励设置 ${itemId}`);
        }
        return false;
    }

    toMixItemByQuality(unit: UnitModel, materialInfos: MaterialInfo[], loc?: LocModel): boolean {
        const player = PlayerFactory.getInstance().getUnitOwner(unit);
        Logger.toastMix('------品质合成系统-------', player);

        const checkMixRet = this.checkToMixByQuality(player, materialInfos);
        const newQuality = checkMixRet.newQuality;
        const funs = checkMixRet.funs;
        const qualitySetting: QualitySetting[] = Configer.getConfig(ConfigKey.qualitySetting);
        const qualitySet = qualitySetting[newQuality];
        const boxId = qualitySet?.lvBox;
        if (newQuality && newQuality >= 0) {
            // 合成成功 创建高一品质的物品
            if (!CodeUtil.isNullOrZero(boxId)) {
                if (boxId) {
                    funs.map((value, index, array) => {
                        value();
                    })
                    TaskController.getInstance().rewardItem(unit, RewardType.bag, boxId);
                    return true;
                } else {
                    Logger.toastMix('没有设定更高一级的装备', player);
                }
            } else {
                const ids = DataRouter.getGoodIdsByQuality(newQuality);
                if (ids && ids.length && ids.length > 0) {
                    funs.map((value, index, array) => {
                        value();
                    })
                    const len = ids.length;
                    const random = player.getRandomInt(0, len - 1);
                    const goodId = ids[random];
                    // Logger.toastProduct('合成成功', player);
                    if (loc) {
                        TaskController.getInstance().rewardItem(unit, RewardType.floor, goodId, 0, loc);
                    } else {
                        TaskController.getInstance().rewardItem(unit, RewardType.bag, goodId);
                    }
                    // GoodController.getInstance().reflushGoodsBar(player);
                    return true;
                } else {
                    Logger.toastMix('没有设定更高一级的装备', player);
                }
            }
        } else {
            Logger.toastMix('合成物不足', player);
        }
        return false;
    }

    checkToMixByQuality(player: PlayerModel, mixGoodsInfos: MaterialInfo[]) {
        const checkMixRet: { newQuality: number, funs: (() => void)[] } = {newQuality: undefined, funs: []};
        // 第一维是品质 第二维是参与合成的物品信息;
        const mixCounts: number[] = [];

        const qualitySetting: QualitySetting[] = Configer.getConfig(ConfigKey.qualitySetting);
        const maxQuality = qualitySetting.length
        for (let i = 0; i <= maxQuality; i++) {
            mixCounts[i] = 0;
        }

        const funMap: { [quality: number]: (() => void)[] } = {};
        // 遍历当前物品组，判断物品组中物品是否符合合成条件
        for (let itemIndex = 0; itemIndex < mixGoodsInfos.length; itemIndex++) {
            const mixGoodsInfo = mixGoodsInfos[itemIndex];
            const currentId = mixGoodsInfo.id;
            const currentNum = mixGoodsInfo.num;
            const deleteFun = mixGoodsInfo.deleteFun;
            const changeNumFun = mixGoodsInfo.changeNumFun;

            const goodsData = DataRouter.getItemDataByItemId(currentId);

            if (goodsData) {
            } else {
                continue;
            }

            const quality = goodsData.quality;

            // 品质合成目前只支持装备,装备不允许叠加
            const itemNum = 0;

            if (quality && quality >= 0) {
                let fun;
                if (currentNum > itemNum) {
                    Logger.toastMix('合成表中有此物品，并且数量比需要的更多', player);
                    const newNum = currentNum - itemNum;
                    fun = () => {
                        changeNumFun(newNum);
                    }
                } else if (currentNum === itemNum) {
                    Logger.toastMix('合成表中有此物品，并且数量和需要一样多', player);
                    fun = () => {
                        deleteFun();
                    }
                } else {
                    Logger.toastMix(`合成表中有此物品，但数量不足: 需要${itemNum}，却只有${currentNum}`, player);
                }

                if (fun) {
                    const funs = funMap[quality];
                    if (funs) {
                        funs.push(fun);
                    } else {
                        funMap[quality] = [fun]
                    }
                }

                if (mixCounts[quality] && mixCounts[quality] >= 0) {
                    mixCounts[quality] = mixCounts[quality] + 1;
                } else {
                    continue;
                }
                const currentLen = mixCounts[quality];
                const qualitySet: QualitySetting = qualitySetting[quality];
                const qualityMixNum = qualitySet.mixNum;
                if ((!CodeUtil.isNullOrZero(qualityMixNum)) && currentLen >= qualityMixNum) {
                    const newQuality = quality + 1;
                    const ids = DataRouter.getGoodIdsByQuality(newQuality);
                    if (ids && ids.length && ids.length > 0) {
                        checkMixRet.newQuality = newQuality;
                        checkMixRet.funs = funMap[quality];
                        break;
                    }
                }
            }
        }
        return checkMixRet;
    }
    toMixItemByMixData(unit: UnitModel, item: ItemModel, materialInfos: MaterialInfo[]): boolean {
        const player = PlayerFactory.getInstance().getUnitOwner(unit);
        const itemId = item.strId;
        const mixArr = DataRouter.getMixDatasByItemId(itemId);
        if (mixArr) {
        } else {
            return false;
        }
        Logger.toastMix('------合成系统-------', player);
        Logger.toastMix(`当前装备的合成公式数量: ${mixArr?.length}`, player);

        const ret = this.checkToMixByMixDatas(materialInfos, mixArr);
        if (ret) {
        } else {
            return false;
        }
        const mixId = ret.mixId;
        const funs = ret.funs;
        if (mixId) {
            const successMixData = DataRouter.getMixDatasByMixId(mixId);
            if (successMixData) {
                const conditions = successMixData.condition;
                const conditionArr = CodeUtil.getArrBySplit(conditions);
                const bCheck = TaskController.getInstance().checkConditions(unit, conditionArr, undefined, player);
                if (bCheck.success) {
                    funs.map((value, index, array) => {
                        value();
                    })
                    const reward = successMixData.reward;
                    // Logger.toastProduct('合成成功', player);
                    TaskController.getInstance().reward(unit, unit, RewardType.bag, reward);
                    const request: BroadcastRequest = { broadcastType: BroadcastType.updateGui, controllerNo: ControllerNo.GuiController, data: { guiId: GuiId.goodsBar, player: player } }
                    ControllerBroadcast.getInstance().broadcast(request);
                    return true;
                } else {
                    Logger.toastMix('合成条件未通过', player);
                }
            } else {
                Logger.toastError(`合成成功 但返回的ID不正确 ${mixId}`)
            }
        } else {
            Logger.toastMix('合成物不足', player);
        }
        return false;
    }
    checkToMixByMixDatas(mixGoodsInfos: MaterialInfo[], mixDatas: MixData[]) {
        const checkMixRets = Util.checkToMixByMixDatas(mixGoodsInfos, mixDatas);
        const keys = Object.keys(checkMixRets);
        const key = keys[0];
        const checkMixRet: MixRet = checkMixRets[key];
        return checkMixRet;
    }

    getMixGoodsInfoInUnitBag(unit: UnitModel, item?: ItemModel) {
        const player = PlayerFactory.getInstance().getUnitOwner(unit);
        const goodsBags = player.data[PlayerDataKey.goodsBag];
        const mixGoodsInfos: MaterialInfo[] = [];
        if (item) {
            const tempGoodInfo = item;
            const mixGoodsInfo: MaterialInfo = {
                id: tempGoodInfo.strId,
                num: tempGoodInfo.charges,
                deleteFun: () => {
                    if (item) {
                        ModelFactory.getInstance().unitRemoveItem(unit, item);
                    }
                },
                changeNumFun: (num) => {
                    if (item) {
                        item.charges = num;
                    }
                }
            }
            mixGoodsInfos.push(mixGoodsInfo);
        }


        unit.mapItems((slotItem) => {
            if (slotItem.equal(item)) {
                return false;
            }
            const mixGoodsInfo: MaterialInfo = {
                id: slotItem.strId,
                num: slotItem.charges,
                deleteFun: () => {
                    if (slotItem) {
                        ModelFactory.getInstance().unitRemoveItem(unit, slotItem);
                    }
                },
                changeNumFun: (num) => {
                    if (slotItem) {
                        slotItem.charges = num
                    }
                }
            }
            mixGoodsInfos.push(mixGoodsInfo);
        })
        const maxGoodsBagNum = Configer.getConfig(ConfigKey.maxGoodsBagNum);
        for (let goodsIndex = 0; goodsIndex < maxGoodsBagNum; goodsIndex++) {
            const itemModel = goodsBags[goodsIndex];
            const currentIndex = goodsIndex;
            if (itemModel) {
                const mixGoodsInfo: MaterialInfo = {
                    id: itemModel.strId,
                    num: itemModel.charges,
                    deleteFun: () => {
                        // const realIndex = goodsBags.indexOf(goodsInfo);
                        const realIndex = currentIndex;
                        if (realIndex >= 0) {
                            goodsBags[realIndex] = undefined
                        }
                    },
                    changeNumFun: (num) => {
                        itemModel.charges = num;
                    }
                }
                mixGoodsInfos.push(mixGoodsInfo);
            }
        }
        return mixGoodsInfos;
    }

    mapTaskSerialize(index: number, bAll: SerializeLoadType, callBack: (key: string, index: number, taskId: string) => void) {
        const taskDatas = DataRouter.getTaskDatas();
        const archiveFun = (archiveIndex: number) => {
            for (let i = 0; i < taskDatas.length; i ++) {
                const taskData = taskDatas[i];
                const taskId = taskData.id;
                const save = taskData.save;
                let key;
                switch (save) {
                    case SaveType.archive: {
                        key = `${taskId}_${archiveIndex}`
                        break;
                    }
                }
                if (!CodeUtil.isNullOrZero(key)) {
                    callBack(key, i, taskId);
                }
            }
        }
        const globalFun = () => {
            for (let i = 0; i < taskDatas.length; i ++) {
                const taskData = taskDatas[i];
                const taskId = taskData.id;
                const save = taskData.save;
                let key;
                switch (save) {
                    case SaveType.global: {
                        key = `${taskId}_g`
                        break;
                    }
                }
                if (!CodeUtil.isNullOrZero(key)) {
                    callBack(key, i, taskId);
                }
            }
        }

        switch (bAll) {
            case SerializeLoadType.current_global: {
                globalFun();
            }
            case SerializeLoadType.current_archive: {
                const archiveIndex = index;
                archiveFun(archiveIndex);
                break;
            }
            case SerializeLoadType.all_global: {
                globalFun();
            }
            case SerializeLoadType.all_archive: {
                const maxArchiveNum = Configer.getConfig(ConfigKey.maxArchiveNum);
                for (let i = 0; i < maxArchiveNum; i++) {
                    const tempIndex = i + 1;
                    archiveFun(tempIndex);
                }
                break;
            }
        }
    }
}